<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>

  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="Generator" content="Emacs, Lisp, Python, Linux">
    <meta name="Keywords" content=",GNU,Linux,Lisp,FreeBSD,C,Emacs,Python,Java,JOY工作室">
    <meta name="Description" content="无很的主页，热爱GNU/Linux，GNU/Lisp的忠实粉丝">
    <meta name="Author" content="无很">
    <meta name="Robots" content="index">
    <link rel="stylesheet" type="text/css" charset="utf-8" media="all" href="../style.css">
    <title>Lisp快速入门
	</title>
  </head>
  
  <body>

    <div class="menu">
      <a title="无很主页" href="http://www.lisperblog.com">Lisperblog</a>
      <a title="无很的主页" href="/index.html">主页</a>
      <a href="/Lisp/index.html">Lisp</a>
	  <a href="/Python/index.html">Python</a>
	  <a href="/Java/index.html">Java</a>
	  <a href="/Linux/index.html">Linux</a>
	  <a href="/FreeBSD/index.html">FreeBSD</a>
      <a title="关于我，联系信息" href="/About.html">联系</a>
    </div>

    <div id="header">
      <h1 >Lisp快速入门</h1>
      <!--<h2><a href="mailto:wuhen86@gmail.com">author:无很</a></h2>-->
    </div>

    <div id="main">
<!-- Emacs Muse 正文发布从此开始 -->
<h4>Lisp中的7个基本运算符</h4>

<p class="first">1. <em>quote</em></p>

<p>quote可以简写为&quot;'&quot;,它的求值规则是什么都不做。quote的含义是引用，它的作用是原样返回表达式内容。对所操作的参数不予求值。这就意味着数据和代码由相同的数据结构构成的。</p>

<p>2. <em>atom</em></p>

<p>(atom x)如果x的值是一个原子或是空表则返回t或T，否则返回()或nil。</p>

<pre class="example">
 (atom 'a)        =&gt;t
 (atom 2)         =&gt;t
 (atom '(1 2 3))  =&gt;nil
 (atom ())        =&gt;t
 (atom '())       =&gt;t
</pre>

<p>3. <em>eq</em></p>

<p>(eq x y)如果x，y的值是同一个原子或都为空表则返回t，否则返回空表()(即nil)</p>

<pre class="example">
 (eq 'a 'a)        =&gt;t
 (eq 'a 'b)        =&gt;nil
 (eq '() '())      =&gt;t
 (eq '() ())       =&gt;t
 (eq '(a) '(a))    =&gt;nil ;'(a)不是原子
</pre>

<p>4. <em>car和cdr</em></p>

<p>car和cdr都只有一个参数，并且参数只能是一个表。car返回参数(list)的第一个元素，cdr返回参数（list)的第一个元素之后的其他元素。</p>

<p>5. <em>cons</em></p>

<p>(cons x y)返回一个表，第一个元素是x，其后是y的所有元素。如果y是一个原子，返回一个.表示的列表。否则返回一个列表。</p>

<pre class="example">
 (cons 'x 'y)                   =&gt;(x y)
 (cons 'x '(a b c))             =&gt;(x a b c)
 (cons 'x 1)                    =&gt;(x . 1)
 (cons '(a b) 3)                =&gt;((a b) . 3)
</pre>

<p>6. <em>cond</em></p>

<p>cond是lisp的条件操作符，cond的形式如下：</p>

<pre class="example">
 (cond (p1 e1)
       (p2 e2)
       (p3 e3)
        ...
       (pn en))
</pre>
p1到pn为条件，e1到en为结果，cond依次对p1到pn求值，直到找到第一个值为t的就执行对应的表达式e，并将表达式e的值做整个表达式的值为返回。如果所有条件都不满足则返回nil。如果有一个p为t，但没有对应的e，则返回p的值t。


<h4>变量与赋值</h4>

<p class="first">Lisp中的变量定义主要有defvar、defparameter、setf、let及其变种。以下解释各个宏的不同之处：</p>

<ul>
<li>defparameter的形式是：(defparameter key value) 它的作用是将符号key与值value绑定。</li>
<li>defvar的形式是:(defvar key [value])。其中value是可以省略的，如果省略，defvar将只声明变量key而不绑定任何值；如果在defvar之前已经定义了key并绑定了值，defvar将不再绑定。如下所示：</li>
</ul>

<pre class="example">
 (defvar *g*)                       =&gt;*G*  ;;只定义了*g*没绑定值
 *g*                                =&gt;error:unbound variable *G* ;;*g*值未绑定
 (defvar *g* 'a)                    =&gt;*G*  ;;绑定值
 *g*                                =&gt;A
 (defvar *g* 'b)                    =&gt;*G*  ;;再次定义变量
 *g*                                =&gt;A    ;;显示第一次绑定的值A
</pre>

<ul>
<li>setf，严格来说setf是对变量赋值的宏。也可以对多个变量赋值。形式如下：</li>
</ul>

<pre class="example">
 (setf var1 val1 var2 val2 ...)
</pre>
这里要说明的是如果变量在赋值前没有被定义，setf会自动定义一个全局变量或特殊变量来与值绑定。

<pre class="example">
 (let ((s 'a))
      (print s)                  =&gt; A
      (setf s 'b)
      (setf ss 'abc)             ;定义一个新的变量ss(全局变量)
      (print s))                 =&gt; B

 (print s)                       =&gt; error:unbound variable &quot;S&quot;
 (print ss)                      =&gt; ABC
</pre>

<ul>
<li>let用来定义局部变量，形式如下：</li>
</ul>

<pre class="example">
 (let ((var1 exp1) (var2 exp2) ...(varn expn))
       exps)
</pre>
变量var1..n只在let作用域内有效，所以叫局部变量。let返回整个let语句的最后一条语句的值。
顺便说下lisp中定义常量是defconstant语句(宏):(defconstrant key const-value)。
判断一个符号是否已经被定义为全局变量或常量可用boundp宏。

<ul>
<li>Lisp的作用域</li>
</ul>

<p>Lisp的作用域分为词法作用域和动态作用域.Scheme是最早有词法作用域(lexically scope)的方言;在它之前动态作用域(dynamic scope)被视为lisp的本质属性之一.词法作用域和动态作用域的区别在于语言处理自由变量的方式不同,当一个符号被用来表达变量时,我们称这个符号在表达式中是被绑定的.这里的变量也可以是参数,也可以是像let和do这样的变量绑定操作符.如果变量不受到约束就认为它是自由的.如下:</p>

<pre class="example">
 (let ((y 7))
      (defun scope-test(x)
         (list x y)))
</pre>
在函数表达式里,x是受约束的,而y是自由的.一个约束变量的值是当调用时通过参数传给它的值.而y值是什么呢?这就要看具体的实现了.

<p>在动态作用域的lisp里,要想找出当scope-test执行时的自由变量的值,我们就要往回逐个检查调用的函数链,当发现y被绑定时,这个被绑定的值即被用在scope-test中.如果没有发现就取y的全局值.在样在动态作用域的lisp里,在调用的时候y将产生这样的值:</p>

<pre class="example">
 (let ((y 5))
   (scope-test 3))                    =&gt; (3 5)
</pre>
在词法作用域的lisp里,我们不再往回逐个检查函数的调用链,而是逐个检查定义这个函数时它所处的外部环境.在一个词法作用域的lisp里,我们的示例将捕捉到定义scope-test时y的值,所以在词法作用域的lisp里,上述代码将返回(3 7).

<p>Common Lisp默认是词法作用域.</p>


<h4>输入输出</h4>

<p class="first">Common Lisp最常用的输出命令是format.用法如下:</p>

<pre class="example">
 (format t &quot;~%The clever dog can do ~A+~A=~A&quot; 2 3 5)           =&gt; The clever dog can do 2+3=5
</pre>
format的第一个参数是输出地,t代表输出到toplevel并返回nil,nil代表输出结果但不返回nil;第二个参数是输出格式,~%表示换行,~A表示将有参数替换.~S可以打印出控制符而~A不能.~P打印复数后缀s.

<p>~D,~B,~O,~X,~R为整数控制符,分别打印出十进制,二进制,十六进制,基数.</p>

<p>~E,~F,~G,~$为浮点控制符,分别按指定格式,定点格式,浮点格式,浮点定点结合方式.</p>

<p>~n%,~n&amp;,~|为空白控制符.分别表示换n行,n-1行,新一页.</p>

<p>Common Lisp的标准输入运算符是read,通常是从toplevel输入,直到遇到回车符为止.</p>


<h4>条件</h4>

<p class="first">Lisp中t表示真,nil表示假.一般情况下,函数名以p结尾的lisp函数用于检测对象是否具有某种属性.如:symbolp,boundp,listp,keywordp,fboundp,numberp,typep,oddp,evenp,zerop.Lisp中最简单的条件操作符是if,用法如下:</p>

<pre class="example">
 (if test exp1 exp2)
</pre>
表达式test为真则返回exp1,否则返回exp2.exp2可以省略,但如果test是nil的话则返回nil.需要注意的是exp1和exp2都是单一表达式,如果需要多表达式完成多个处理,则要使用progn.用法是:
&lt;example&gt;
<blockquote>
<p class="quoted">(progn
exp1
exp2
expn)
&lt;example&gt;</p>
</blockquote>


<h4>循环</h4>


<!-- Emacs Muse 正文发布至此结束 -->
</div>

<div id="footer">
 <!-- <div id="visitcounter">
   您是第 <img border="0" src="http://cb.amazingcounters.com/counter.php?i=2660657&c=7982284" alt="统计"> 位访问者
  </div> -->
  <div id="copyright">
   &copy; 2012 <a href="http://www.lisperblog.com">JOY工作室</a>
  </div>
  <div id="footdate">
    最后更新 ： 2012 年 03 月 03 日
  </div>
  <!--<script language="javascript" type="text/javascript" src="http://js.users.51.la/3151082.js"></script>
  <noscript><a href="http://www.51.la/?3151082" target="_blank"><img alt="51统计" src="http://ylinux.org/ylinux/media/default/ylinux/images/51.gif"/></a></noscript> -->
</div>

</body>
</html>
